#include <sys/types.h>
#include <sys/socket.h>

#include <arpa/inet.h>

#include <netinet/in.h>
#include <netinet/ip.h>

#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>

#include <errno.h>

#include <signal.h>

#include <math.h>
#include <limits.h>

#include "inc/qd_utils.h"
#include "inc/qd_datas.h"
#include "inc/qd_types.h"


#include "inc/SocketManager.h"
#include "inc/FileIO.h"
#include "inc/NetFileIO.h"
#include "inc/FileTask.h"

void handleSignal(int signal) {
    if (signal == SIGINT) {
        printf("Program Exit\n");
        exit(1);
    }
}

int isRemote(const char *str){
    return strchr(str,':') || strchr(str, '@');
}

void GetParam(char *_str, char *user, char *ip, char *path){
        char *index = _str;
        char *at = strchr(index,'@');
        char *address = strchr(index,':');

        int len = strlen(index);
        strncpy(user, index, at - index); at++;
        strncpy(ip, at, address - at); address ++;
        strcpy(path, address);
}

int Upload(FileIO *localFile, int svrFd);
int Download(FileIO *localFile, int svrFd);

int main(int argc, char *argv[]){

    char user[16];
    char ip[16];
    char remote_file[127];

    char local_file[127];

    OP_MODE mode = OP_MODE_NULL;

    memset(local_file, 0 , sizeof(local_file));
    memset(remote_file, 0 , sizeof(remote_file));

#if 1
    if(argc == 3){
        if(isRemote(argv[1]) && !(isRemote(argv[2]))){
            GetParam(argv[1], user, ip, remote_file);
            strcpy(local_file, argv[2]);
            mode = OP_DOWNLOAD;
        }
        if( !(isRemote(argv[1])) && isRemote(argv[2])){
            strcpy(local_file, argv[1]);
            GetParam(argv[2], user, ip, remote_file);
            mode = OP_UPLOAD;
        } 
    }
#endif

    EndPoint svr(ip, 8848);

    svr.Connect();

    if(mode == OP_DOWNLOAD){

        QDReqParams cFile;
        memset(&cFile, 0 , sizeof(QDReqParams));

        cFile.mode = mode;

        strcpy(cFile.user, user);
        strcpy(cFile.path, "/");

        strcpy(cFile.name, remote_file);


        svr.Request(&cFile, sizeof(QDReqParams), &cFile, sizeof(QDReqParams));


        QD_LOGD("%d", cFile.blockSize);

        FileIO localFile(local_file, cFile.blockSize, 0);

        Download(&localFile, svr.mFd);

    } else if( mode == OP_UPLOAD){

        FileInfo fInfo(local_file);  // 读取本地文件信息

        QDReqParams cFile;
        memset(&cFile,0, sizeof(QDReqParams));

        strcpy(cFile.user, user);
        strcpy(cFile.path, "/");

        cFile.mode = OP_UPLOAD;

        // 文件名
        strcpy(cFile.name, fInfo.getName());
        
        // 文件大小
        cFile.size = fInfo.getSize();

        svr.Request(&cFile, sizeof(QDReqParams), &cFile, sizeof(QDReqParams));

        FileIO localFile(local_file, cFile.blockSize, cFile.size);

        Upload(&localFile, svr.mFd);
    }
   // QD::Close(&svr);
    return 0;
}


int Upload(FileIO *localFile, int svrFd){
    localFile->Open("r");

    NetFileIO   nIO(svrFd, localFile->getBlockSize());

    QD_LOGD("push mode");

    char buff[8192];

    int rSize = 0;

    while(1){
        rSize = localFile->Read(buff, localFile->getBlockSize());
        nIO.Write(buff, rSize);

        if(rSize <= 0){
            break;
        }

    }

    return 0;
}

int Download(FileIO *localFile, int svrFd){
    localFile->Open("w");

    NetFileIO   netFile(svrFd, localFile->getBlockSize());

    char buff[8192];
    // 简化成普通读写操作
    while(1){
        memset(buff, 0, sizeof(buff));

        // 读取 buff
        int rSize = netFile.Read(buff);

        if(rSize <= 0){
            break;
        }

        // 写入buff
        localFile->Write(buff, rSize);

    }

    return 0;
}

